package com.semidata.trp.report.service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import com.semidata.rtd.core.http.server.HttpSession;
import com.semidata.rtd.core.log.Logger;
import com.semidata.rtd.core.service.SendableService;
import com.semidata.trp.report.config.Config;
import com.semidata.trp.report.report.NRTReport;
import com.semidata.trp.report.report.SortLogs;

public class ReportService implements SendableService<HttpSession> {
	private volatile boolean quit = false;
	private Thread sortThread = null;
	private Thread reportThread = null;
	private long nextDayStart = 0;
	private final long round = Config.getConfig().getRound();
	private final int dayStart = Config.getConfig().getDayStart();
	private List<String> lastMiss = new ArrayList<>();
	private List<String> currentMiss = new ArrayList<>();
	private String currentDate = null;

	public void start() {

		final SimpleDateFormat monthformat = new SimpleDateFormat("yyyyMM");
		final SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd");
		final SimpleDateFormat minuteformat = new SimpleDateFormat(
				"yyyyMMddHHmm");

		sortThread = new Thread(new Runnable() {
			public void run() {
				Calendar startTime = new GregorianCalendar();
				startTime.set(Calendar.HOUR_OF_DAY, 0);
				startTime.set(Calendar.MINUTE, 0);
				startTime.set(Calendar.SECOND, 0);
				currentDate = dateformat.format(startTime);
				Calendar nowTime = new GregorianCalendar();
				currentDate = dateformat.format(nowTime);
				nowTime.set(Calendar.MINUTE, nowTime.get(Calendar.MINUTE) - 10);
				final long time = nowTime.getTimeInMillis();
				long start, end;
				String minute, date = currentDate;
				while (true) {
					if (startTime.getTimeInMillis() < time) {
						minute = minuteformat.format(startTime);
						currentMiss.add(minute);
					} else {
						break;
					}
					startTime.set(Calendar.MINUTE,
							startTime.get(Calendar.MINUTE) + 1);
				}

				final SortLogs sorter = new SortLogs();
				sorter.setAllList(currentDate);
				while (!quit) {
					if (date.compareTo(currentDate) != 0) {
						currentDate = date;
						lastMiss.clear();
						lastMiss.addAll(currentMiss);
						currentMiss.clear();
					}
					start = System.currentTimeMillis();
					minute = minuteformat.format(startTime);
					try {
						sorter.setFilesByMinute(minute);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						Logger.log("ERROR", "sort error " + minute);
						currentMiss.add(minute);
					}
					startTime.set(Calendar.MINUTE,
							startTime.get(Calendar.MINUTE) + 1);
					date = dateformat.format(startTime);
					end = System.currentTimeMillis();
					start = end - start;
					try {
						Thread.sleep(60 * 1000 - start);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});
		sortThread.start();

		reportThread = new Thread(new Runnable() {
			public void run() {
				Calendar c = new GregorianCalendar();
				final SortLogs sorter = new SortLogs();
				final NRTReport nrtReport = new NRTReport();
				String date;
				while (!quit) {
					c = Calendar.getInstance();
					if (c.getTimeInMillis() >= nextDayStart) {
						c.set(Calendar.DAY_OF_MONTH,
								c.get(Calendar.DAY_OF_MONTH) - 1);
						date = dateformat.format(c.getTime());
						if (lastMiss != null && !lastMiss.isEmpty()) {
							sorter.setAllList(date);
							for (String minute : lastMiss) {
								try {
									sorter.setFilesByMinute(minute);
								} catch (Exception e) {
									Logger.log("ERROR", "date : " + date
											+ ",minute : " + minute
											+ "finally sort error");
								}
							}
						}
						try {
							sorter.finalSort(date);
						} catch (Exception e) {
							Logger.log("ERROR", date);
							Logger.log("ERROR", e.getMessage());
						} finally {
							setNextDay(Calendar.getInstance());
						}
						try {
							nrtReport.setFileList(date, 2, false);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							Logger.log("ERROR", e.getMessage());
						}
					}
					c = Calendar.getInstance();
					if(c.get(Calendar.DAY_OF_MONTH) == 1){
						c.set(Calendar.MONTH, c.get(Calendar.MONTH) - 1);
						date = monthformat.format(c.getTime());
						try {
							nrtReport.setFileList(date, 3, false);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							Logger.log("ERROR", e.getMessage());
						}
					}
					setNextDay(Calendar.getInstance());
					try {
						Thread.sleep(round);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						Logger.log("ERROR", e.getMessage());
					}
				}
			}
		});
		reportThread.start();
	}

	public void stop() {
		quit = true;
		try {
			if (reportThread != null) {
				reportThread.join();
			}
			if (sortThread != null) {
				sortThread.join();
			}
		} catch (Exception e) {
			Logger.log("ERROR", e.getMessage());
		}
	}

	public void send(HttpSession event) {
		// TODO Auto-generated method stub

	}

	public void setNextDay(Calendar c) {
		c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + 1);
		c.set(Calendar.HOUR_OF_DAY, dayStart);
		c.set(Calendar.MINUTE, 0);
		nextDayStart = c.getTimeInMillis();
	}
}
